
#ifndef _WEBELEMENT_H_
#define _WEBELEMENT_H_

#include "WebKitPort.h"
#include "WebKitCaller.h"
#include "KeyType.h"
#include <list>
#include <stdio.h>

namespace SpiderWebKitClient {

typedef struct _WebElementRect {
    int x;
    int y;
    int w;
    int h;
} WERect;

class WebPage;

/*
 * @classname WebElement
 * @classdesc 对应服务端的一个页面元素实例
 */
class WebElement {
    public:

    WebElement();
    WebElement(long element, long pageRef, WebKitCaller *caller);
    ~WebElement();

    long ref() { return m_ref; }
    long pageRef() { return m_pageRef; }
    WebKitCaller* caller() { return m_caller; }

    bool isValid() { return m_ref <= 0 ? false : true; }

    /*
     * @class WebElement
     * @func std::list<WebElement> getChildsByCssSelector(std::string query);
     * @desc 获取该元素子元素中符合css selector所指定的元素列表
     * @parm query css selector string
     * @return 元素列表
     */
    std::list<WebElement> getChildsByCssSelector(std::string query);

    /*
     * @class WebElement
     * @func std::string getTagName();
     * @desc 获得当前元素的标签名称
     * @return 标签名称
     */
    std::string getTagName();

    /*
     * @class WebElement
     * @func std::string getAttribute(std::string name);
     * @desc 获得当前元素的名为name的属性值
     * @parm 属性名称
     * @return 属性值
     */
    std::string getAttribute(std::string name);

    /*
     * @class WebElement
     * @func void setAttribute(std::string name, std::string value);
     * @desc 设置当前元素name属性的属性值
     * @parm name 属性名称
     * @parm value 要设定的属性值
     */
    void setAttribute(std::string name, std::string value);

    /*
     * @class WebElement
     * @func void removeAttribute(std::string name);
     * @desc 删除当前元素的某一属性
     * @parm name 想要删除的属性
     */
    void removeAttribute(std::string name);

    std::string getProperty(std::string name);

    /*
     * @class WebElement
     * @func std::string getText();
     * @desc 获取当前元素的文本
     * @return 当前元素内的文本
     */
    std::string getText();

    /*
     * @class WebElement
     * @func std::string getValue();
     * @desc 获取当前元素value属性的值
     * @return value属性的值
     */
    std::string getValue();

    /*
     * @class WebElement
     * @func long sendKeys(std::string type, long keys);
     * @desc 向当前元素发送键值,该接口为异步调用,调用之后即返回
     * @parm type 按键动作类型(keypress/keydown/keyup)
     * @parm keys 键值, 枚举Keys中定义
     * @return 1 成功
     */
    long sendKeys(std::string type, long keys);

    /*
     * @class WebElement
     * @func long type(std::string val);
     * @desc 向当前元素输入文本,多为操作input元素
     * @parm val 想要输入的文本
     * @return 1 成功
     */
    long type(std::string val);

    /*
     * @class WebElement
     * @func long setValue(std::string val);
     * @desc 设置当前元素的value属性
     * @parm val value值
     * @return 1 成功
     */
    long setValue(std::string val);

    /*
     * @class WebElement
     * @func long submit();
     * @desc 提交表单,异步,调用即返回
     * @return 1 成功
     */
    long submit();

    /*
     * @class WebElement
     * @func long click();
     * @desc 点击当前元素,异步，调用即返回
     * @return 1 成功
     */
    long click();

    long reset();

    long toggle();

    /*
     * @class WebElement
     * @func long focus();
     * @desc 将当前元素设置成焦点元素
     * @return 1 成功
     */
    long focus();

    long selected();

    long setSelected(bool selected);

    /*
     * @class WebElement
     * @func long checked();
     * @desc 查看当前元素是否被选中,用于checkbox元素
     * @return  1 选中, 0 未选中
     */
    long checked();

    /*
     * @class WebElement
     * @func long setChecked(bool checked);
     * @desc 设置当前元素的选中状态,用于checkbox元素
     * @parm checked true 选中当前元素, false 取消选中
     * @return 1 成功
     */
    long setChecked(bool checked);

    /*
     * @class WebElement
     * @func long selectOptionByIndex(int index);
     * @desc 选中select的option
     * @parm index option index
     * @return 1 成功
     */
    long selectOptionByIndex(int index);

    long stale();

    /*
     * @class WebElement
     * @func bool isVisible();
     * @desc 查看当前元素是否可见
     * @return true 可见, false 隐藏
     */
    bool isVisible();

    long drag(int toX, int toY, int duration);

    /*
     * @class WebElement
     * @func WERect getRect();
     * @desc 获得当前元素在页面上所处的矩形区域
     * @return 当前元素在页面上所处的矩形区域
     */
    WERect getRect();

    /*
     * @class WebElement
     * @func std::string getInnerXml();
     * @desc 获得当前元素内的html代码
     * @return 当前元素内的html代码
     */
    std::string getInnerXml();

    /*
     * @class WebElement
     * @func std::string getOuterXml();
     * @desc 获取当前元素的html代码,包括当前元素
     * @return 当前元素的html代码
     */
    std::string getOuterXml();

    /*
     * @class WebElement
     * @func bool getImageBuffer(std::vector<char> &output);
     * @desc 将当前元素渲染成图片
     * @return png图片格式的Buffer
     */
    bool getImageBuffer(std::vector<char> &output);

    /*
     * @class WebElement
     * @func bool waitForInnerXml(unsigned int times);
     * @desc 等待当前元素内渲染出内容
     * @parm 查询次数,200ms查询一次
     * @return true 渲染出内容, false 规定次数内未查到渲染成功
     */
    bool waitForInnerXml(unsigned int times);

    /*
     * @class WebElement
     * @func bool isFailed();
     * @desc 当服务调用超时(1分钟没有返回),则认为到服务器端的连接已经失效,之后到服务器的这个连接对应的调用都将返回空,调用该接口返回true,此时,你应该重新发起对应page的请求并重新解析获得该webelement.
     * @return true 失败，false 没有失败
     */
    bool isFailed();



    private:
    WebKitCaller *m_caller;
    long m_ref;
    long m_pageRef;
};

} // namespace SpiderWebKitClient

#endif
